package com.miracle.tears.manager;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.miracle.tears.pojo.WBContentPojo;
import com.miracle.tears.util.FileOperatorUtil;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

/** 数据准备管理器类，主要是为了解决数据的由行到对象的准备环节 */
public class DataPrepareManager {
  /**
   * 给定文件夹和编码，拿到content类型的目录下面 所有的文件 对应的uid和lineList的map集合 其中 key 是 id value 是 全部评论内容
   *
   * @param dirPath 给定文件目录
   * @param charset 编码
   * @return map集合 key 存储 id ， value 存储 lineList
   * @throws IOException IO异常
   */
  public static Map<String, List<String>> getUidAndLineList4Content(String dirPath, String charset)
      throws IOException {
    // 首先拿到该文件夹对应的所有文件路径的集合
    List<String> filePathList = FileOperatorUtil.getFilePathByDirPath(dirPath);

    // 定义一个将uid和文件内容集合对应的 kvMap集合
    Map<String, List<String>> uidAndLineListMap = new HashMap<>();

    // 遍历文件路径列表，获取对应的文件集合
    for (String txtFilePath : filePathList) {
      // 拿到每一个文件对应的数据 单个集合
      List<String> singleFileLineList = FileOperatorUtil.getLineList(txtFilePath, charset);

      // 获取路径对应的文件名称，即 uid
      // 有多种方法，比如通过File，或是通过正则，通过split等。
      String[] pathArray = txtFilePath.split("\\\\");
      String uidValue = pathArray[pathArray.length - 1].split("\\.")[0];

      // 将数据以键值对的形式 存储进入map集合中
      uidAndLineListMap.put(uidValue, singleFileLineList);
    }

    return uidAndLineListMap;
  }

  /**
   * 通过给定的文件夹和编码，拿到对应的抽象出来的内容对象集合
   *
   * @param dirPath 输入路径
   * @param charset 编码
   * @return 数据的 对象集合 再上一步的基础上，将数据存储到对象中
   * @throws IOException io异常
   * @throws DocumentException 文件异常
   */
  public static List<WBContentPojo> getContentPojoList(String dirPath, String charset)
      throws IOException {
    // 调用该方法 得到map形式的集合 数据
    Map<String, List<String>> uidAndLineListMap = getUidAndLineList4Content(dirPath, charset);

    // 定义最终汇总后的 list对象 集合 变量
    List<WBContentPojo> allPojoList = new ArrayList<>();

    // entrySet 适用于10^5以上的数据量 效率高
    Set<Map.Entry<String, List<String>>> entrySet = uidAndLineListMap.entrySet();

    // 通过entrySet()方法将map集合中的映射关系取出，得到的映射关系是Map.Entry类型
    for (Map.Entry<String, List<String>> entry : entrySet) {
      // ID
      String uid = entry.getKey();
      // 评论
      List<String> lineList = entry.getValue();

      for (String xmlLine : lineList) {
        WBContentPojo contentPojo = null;
        try {
          // 将评论内容格式化 规整
          contentPojo = converLineToPojo(xmlLine);
        } catch (DocumentException e) {
          e.printStackTrace();
          System.out.println("出异常了!!!,filepath=" + uid + "，行内容为=" + xmlLine);
        }
        assert contentPojo != null;
        contentPojo.setUid(uid);
        allPojoList.add(contentPojo);
      }
    }

    return allPojoList;
  }

  /**
   * 给定一个xmlLine，解析得到对应的ContentPojo对象
   *
   * @param xmlLine
   * @return 实体对象
   * @throws DocumentException
   */
  public static WBContentPojo converLineToPojo(String xmlLine) throws DocumentException {
    // 对潜在的特殊字符先进行替换，等结果出来后再进行反替换
    // xmlLine=xmlLine.replaceAll("&", "#split#");
    xmlLine = xmlLine.replace("<content>", "<content><![CDATA[");
    xmlLine = xmlLine.replace("</content>", "]]></content>");

    // 获取文档对象
    Document doc = DocumentHelper.parseText(xmlLine);

    // 获取根节点
    Element rootEle = doc.getRootElement();

    // 取得content子元素值
    String content = rootEle.elementText("content");

    // content=content.replaceAll("#split#", "&");           // 转换回来

    // 获取子节点的值
    String time = rootEle.elementText("time");
    String repostsCount = rootEle.elementText("repostsCount");
    String commentsCount = rootEle.elementText("commentsCount");

    return new WBContentPojo("996", content, repostsCount, commentsCount, time);
  }

//  /**
//   * 将组合好的pojoList集合 输出到一个统一的文本文件当中
//   *
//   * @param pojoList
//   * @param outputFilePath
//   * @throws IOException
//   */
//  public static void printPojoToFile(List<WBContentPojo> pojoList, String outputFilePath)
//      throws IOException {
//    for (WBContentPojo pojo : pojoList) {
//      String line =
//          pojo.getUid()
//              + "\001"
//              + pojo.getContent()
//              + "\001"
//              + pojo.getRepostsCount()
//              + "\001"
//              + pojo.getCommentsCount()
//              + "\001"
//              + pojo.getSentTime();
//      FileOperatorUtil.writeLineToFile(outputFilePath, line, true);
//    }
//  }

  /**
   * 将给定的pojoList首行转化成一个大的格式化好的StringBuilder，然后一次性写入
   *
   * @param pojoList
   * @param outputFilePath
   * @throws IOException
   */
  public static void printPojoToFileV2(List<WBContentPojo> pojoList, String outputFilePath)
      throws IOException {
    // 一次性写入
    StringBuilder stringBuilder = new StringBuilder();

    // 无脑实现完美文本文件的无差异读取
    int lineCounter = 0;
    for (WBContentPojo pojo : pojoList) {
      String line =
          pojo.getUid()
              + "\001"
              + pojo.getContent()
              + "\001"
              + pojo.getRepostsCount()
              + "\001"
              + pojo.getCommentsCount()
              + "\001"
              + pojo.getSentTime();

      if (lineCounter > 0) {
        stringBuilder.append("\n");
      }
      stringBuilder.append(line);
      lineCounter++;
    }

    FileOperatorUtil.writeLineToFile(outputFilePath, stringBuilder.toString(), false);
  }

  // 提取出一个content数据准备的入口
  public static void startProcess4Content() throws IOException {
    String dirPath = "S:\\BIGDATA\\项目\\源\\weibodata\\房地产\\content";
    String charset = "gbk";
    String outputFilePath = "DataSummary.txt";

    List<WBContentPojo> allPojoList = DataPrepareManager.getContentPojoList(dirPath, charset);
    DataPrepareManager.printPojoToFileV2(allPojoList, outputFilePath);
  }
}
